#!/usr/bin/env python

"""
*****************************************************************
cellshell.py
This file is part of s60console project.

Released under GNU GPLv2.
See accompanying gpl-2.0.txt file
or visit http://www.gnu.org/licenses/gpl-2.0.txt

Author: Kashif Iftikhar (kashif [at] compulife.com.pk)

Description:
------------
The main module that displays a shell and processes typed commands

*****************************************************************
"""

import cmd
import cmd_processing
import bluetooth
import time

#import libsms
from contacts import contacts

MOBILE_SERVER_PORT = 21
DEFAULT_CELL_BT_ADDR = '00:19:B7:3E:DC:FD'
def dict2xml(d):
    "convert a dictionary object to xml"
    ret = "<cmdinfo>\n"
    for k in d:
        ret += "<%s>%s</%s>" % (k, d[k], k)
    ret += "</cmdinfo>\n"
    return ret

def send_command_to_mobile(bt_addr, cmd_info):
    
    if type(cmd_info) != type( {} ): return
    
    #Process command before sending to mobile.
    cmd_info = cmd_processing.process_cmd(cmd_info)
    
    client_sock=bluetooth.BluetoothSocket( bluetooth.RFCOMM )
    
    target=(bt_addr,MOBILE_SERVER_PORT)
    
    print "Connecting to "+str(target),
    client_sock.connect(target)
    print " ... OK.\n Sending SMS ... ",
    print repr(cmd_info)
    print dict2xml(cmd_info)
    
    client_sock.send(dict2xml(cmd_info))
    print "DONE"
    #status = client_sock.recv(1024)
    #print("Got status: %s" % status)
    time.sleep(1)
    client_sock.close()

class CellShell(cmd.Cmd):
    "Class responsible for displaying the prompt and fetching the commands"
    
    
    intro = """CellShell Version 0.1
Developed by: Kashif Iftikhar (kashif [at] compulife.com.pk)
Released under GNU GPLv2.
    """
    
    prompt = "CellShell> "   #default prompt
    
    CONTACTS = contacts      #contacts
    
    in_multiline_cmd = False
    multiline_cmd = ''
    old_prompt = "CellShell> "
    
    bt_devices = {}          # dictionary containing list of nearby visible bluetooth devices
    current_bt_device = {'dev_name': 'DefaultDev', 'bt_addr': DEFAULT_CELL_BT_ADDR}   # currently being used BT Device
    
    def precmd(self, line):
        #print repr(line)
        if not self.in_multiline_cmd and line.strip().endswith('[[['):
            self.in_multiline_cmd = True
            self.old_prompt = self.prompt
            self.prompt = "[[[>"
        
        if self.in_multiline_cmd:
            self.multiline_cmd += "\n" + line
            if line.strip().endswith(']]]'):
                self.in_multiline_cmd = False
                self.prompt = self.old_prompt
        
        return line
        
    def default(self, line):
        if self.in_multiline_cmd:
            return
        else:
            if '' != self.multiline_cmd:
                #print self.multiline_cmd
                cmd_info = cmd_processing.parse_command(self.multiline_cmd.strip())
                #print repr(cmd_info)
                send_command_to_mobile(self.current_bt_device['bt_addr'], cmd_info)
                self.multiline_cmd = ''
            else:
                print "Unknown command"
    
    def do_EOF(self, line):
        return True
    
    def do_sendsms(self, line):
        """
        Send a text sms
        format:
        
          sendsms contact message
          
        Contact may be: number | name
          number  = [+]X+ (where X is a digit, e.g, +923454564646 or 0435446654)
          name    = contact_name[[index]] (e.g, John, james[0] meaning james first phone number)
          message = string till the end of line
                       OR
                    multi-line string of format [[[ multi-line message ]]]
        """
        
        if not self.in_multiline_cmd:
            cmd_info = cmd_processing.parse_cmd_sendsms(line)
            print repr(cmd_info)
            
            # TODO: select mobile functionality update here.
            send_command_to_mobile(self.current_bt_device['bt_addr'], cmd_info)
        
    
    def complete_sendsms(self, text, line, begidx, endidx):
        
        if not text:
            completions = contacts.keys()
        else:
            completions = [ f
                            for f in contacts
                            if f.startswith(text)
                            ]
        return completions

    def do_discover(self, line):
        """
        Searches for nearby visible bluetooth devices
        """
        nearby_devices = bluetooth.discover_devices(lookup_names = True)
        print "*** discover: found %d devices" % len(nearby_devices)
        #print repr(nearby_devices)
        self.bt_devices = {}
        for addr, name in nearby_devices:
            print "  %s - %s" % (addr, name)
            self.bt_devices[name] = addr
    
    def do_use(self, line):
        "Use specified bluetooth device for all further actions"
        
        line = line.strip()
        
        if not line: return
        
        if ':' == line[2]: # bt-address
            dev_name = line
            if line in self.bt_devices.values():
                for k in self.bt_devices:
                    if self.bt_devices[k] == line:
                        dev_name = k
            
            self.current_bt_device = {'dev_name': dev_name, 'bt_addr': line}
        else:              # bt device name
            if line in self.bt_devices:
                self.current_bt_device = {'dev_name': line, 'bt_addr': self.bt_devices[line]}
            else:
                print "*** use [ERROR]: Device name not present in known devices"
            
        
        self.prompt = "CellShell@%s> " %  self.current_bt_device['dev_name']

    def complete_use(self, text, line, begidx, endidx):
        if not text:
            completions = self.bt_devices.keys()
        else:
            completions = [ f
                            for f in contacts
                            if f.startswith(text)
                            ]
        return completions
    
    def do_import_csv_msgs(self, line):
        "Imports messages from a CSV (or similar) file into the messages DB."
        
    

def _tests():
    "Test cases for the module"
    import sput
    
    T = sput.tester()
    
    #def _test_parse_command():
    #    "Unit tests for the parse_command function"
    #    cmd = "sendsms +92343545454 This is just a simple msg"
    #    valid_r = {'message': ' This is just a simple msg', 'cmd': 'SENDSMS', 'contact': '+92343545454'}
    #    T.add_test("****** prase_command test. single line message command: %s" % cmd, parse_cmd_sendsms, valid_r, cmd)
    #
    #_test_parse_command()
    
    T.run_all_tests()

if __name__ == '__main__':
    import sys
    if len(sys.argv)>1 and 'run_tests'==sys.argv[1]:
        _tests()
        sys.exit()
    
    
    CellShell().cmdloop()

    